package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    public List<MenuVo> menus(Long userId) {
        // 1.获取数据
        List<MenuVo> menuVoList = resourceMapper.selectMenuVoByUserId(userId);
        if (ObjectUtil.isEmpty(menuVoList)) {
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }
        // 2.组装数据
        // 2.1 数据分组
        Map<String, List<MenuVo>> parentNoMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));
        // 遍历所有数据
        menuVoList.forEach(menuVo -> {
            // 补全属性
            menuVo.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
            menuVo.setRedirect("/" + menuVo.getName());

            List<MenuVo> menuVos = parentNoMap.get(menuVo.getResourceNo());
            if (ObjectUtil.isNotEmpty(menuVos)) {
                // 补全属性
                menuVos.forEach(m -> {
                    m.setMeta(MenuMetaVo.builder().title(m.getName()).build());
                    m.setRedirect("/" + m.getName());
                });
            }
            menuVo.setChildren(menuVos);
        });
        return parentNoMap.get(SuperConstant.ROOT_PARENT_ID);
    }

    @Override
    public List<ResourceVo> getResourceList(ResourceDto resourceDto) {
        List<Resource> list = resourceMapper.selectList(resourceDto);
        List<ResourceVo> voList = BeanUtil.copyToList(list, ResourceVo.class);
        return voList;
    }

    @Override
    public TreeVo getTreeList(ResourceDto resourceDto) {
        // 1.获取资源
        //100 001 000 000 000 (一级菜单的父资源编码) 100001000000000
        ResourceDto dto = ResourceDto.builder().parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .dataState(SuperConstant.DATA_STATE_0).build();
        // 获取所有的资源
        List<Resource> resources = resourceMapper.selectList(dto);

        // 2.把资源处理成树形结构
        // 2.1创建 集合 里面装载数据 TreeItemVo
        ArrayList<TreeItemVo> treeItemVos = new ArrayList<>();
        // 2.2手动构建根节点
        Resource root = new Resource();
        root.setResourceNo(SuperConstant.ROOT_PARENT_ID);
        root.setResourceName("智慧养老院");
        // 2.3 处理数据。。。。 递归方法 完成树形结构的整合
        recursionTreeItem(treeItemVos, root, resources);
        return TreeVo.builder().items(treeItemVos).build();
    }

    @Override
    public void addResource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        // 获取父资源信息
        Resource parentResource = resourceMapper.selectByResourceNo(resource.getParentResourceNo());
        // 要和父资源状态保持一致
        resource.setDataState(parentResource.getDataState());
        boolean isFlag = true;
        // 判断要不要进行层级判断，如果是按钮就不用
        if (SuperConstant.BUTTON.equals(resource.getResourceType())) {
            isFlag = false;
        }
        // 根据父资源编号生成资源编号
        String resourceNo = addResourceNo(resource.getParentResourceNo(), isFlag);
        resource.setResourceNo(resourceNo);
        resourceMapper.insert(resource);
    }

    // 修改资源
    @Override
    public void updateResource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        resourceMapper.updateByPrimaryKeySelective(resource);
    }

    // 启用禁用
    @Override
    public void enableSet(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        // 若当前资源为启用，父资源为禁用，直接抛异常
        if (SuperConstant.DATA_STATE_0.equals(resource.getDataState())) {
            // 获取父资源信息
            Resource parentResource = resourceMapper.selectByResourceNo(resource.getParentResourceNo());
            // 如果父资源状态为禁用，那么子资源不能进行启用，否则抛异常
            if (SuperConstant.DATA_STATE_1.equals(parentResource.getDataState())) {
                throw new BaseException(BasicEnum.PARENT_MENU_DISABLE);
            }
        }
        // 若启用父级菜单，父级菜单同子级菜单状态一同变化为启用状态；
        String resourceNo = resource.getResourceNo();
        resourceMapper.enableSetByResourceNo(resourceNo, resource.getDataState());
        resourceMapper.enableSetByParentResourceNo(NoProcessing.processString(resourceNo), resource.getDataState());
    }

    @Override
    public void deleteByResourceNo(String resourceNo) {
        // 判断是否为禁用状态
        Resource resource = resourceMapper.selectByResourceNo(resourceNo);
        // 启用状态不能删除
        if (SuperConstant.DATA_STATE_1.equals(resource.getDataState())) {
            // 禁用状态前提下，再进行处理
            // 如果有下级菜单不能删除
            List<Resource> resources = resourceMapper.selectByParentResourceNo(resource.getResourceNo());
            if (ObjectUtil.isEmpty(resources)) {
                resourceMapper.deleteByResourceNo(resourceNo);
            }else {
                throw new BaseException(BasicEnum.EXIST_CHILDREN_MENU);
            }
        }
    }

    private String addResourceNo(String parentResourceNo, boolean isFlag) {
        // 判断菜单是否大于三级
        if (isFlag && NoProcessing.processString(parentResourceNo).length() / 3 >= 5) {
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        // 获取父资源的子资源
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        List<Resource> resourceList = resourceMapper.selectList(dto);
        if (ObjectUtil.isEmpty(resourceList)) {
            // 当前父资源没有子资源
            return NoProcessing.createNo(parentResourceNo, false);
        } else {
            // 当前父资源有子资源
            // 拿到资源编号最大的子资源
            String maxResourceNo = resourceList.stream().map(s -> s.getResourceNo()).max((o1, o2) -> o1.compareTo(o2)).get();
            return NoProcessing.createNo(maxResourceNo, true);
        }
    }

    private void recursionTreeItem(ArrayList<TreeItemVo> treeItemVos, Resource root, List<Resource> resources) {
        // 1.根据 根节点 Resource 对象 构建 根节点的 TreeItemVo 对象
        TreeItemVo treeItemVo = TreeItemVo.builder().id(root.getResourceNo())
                .label(root.getResourceName()).build();
        // 查找根节点的子节点信息
        List<Resource> childrenList = resources.stream().filter(n -> n.getParentResourceNo().equals(root.getResourceNo()))
                .collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(childrenList)) {
            // 根节点 的子节点不为空 继续处理
            ArrayList<TreeItemVo> listChildren = new ArrayList<>();
            childrenList.forEach(resource -> {
                recursionTreeItem(listChildren, resource, resources);
            });
            treeItemVo.setChildren(listChildren);
        }
        // 把TreeItemVo对象放到集合中
        treeItemVos.add(treeItemVo);
    }
}
